package com.nova.bluetooth.xunFeiSDK.mainFunction;

//TODO 界面修改，增加自定义文本和发音人选择

import android.media.AudioFormat;
import android.media.AudioManager;
import android.media.AudioRecord;
import android.media.AudioTrack;
import android.os.Bundle;
import android.os.Handler;
import android.os.Looper;
import android.util.Log;
import android.view.View;
import android.widget.ScrollView;
import android.widget.TextView;

import androidx.appcompat.app.AppCompatActivity;

import com.iflytek.aiui.AIUIAgent;
import com.iflytek.aiui.AIUIConstant;
import com.iflytek.aiui.AIUIListener;
import com.nova.bluetooth.R;
import com.nova.bluetooth.xunFeiSDK.engine.AiuiEngine;
import com.nova.bluetooth.xunFeiSDK.engine.EngineConstants;
import com.nova.bluetooth.xunFeiSDK.utils.CopyAssetsUtils;
import com.nova.bluetooth.xunFeiSDK.utils.ErrorCode;


public class LocalTTSActivity extends AppCompatActivity implements View.OnClickListener {
    private static final String TAG = LocalTTSActivity.class.getSimpleName();
    Handler handler = new Handler();
    private TextView mResText;
    private ScrollView mScrollView;
    // AIUI
    private AIUIAgent mAIUIAgent = null;
    AudioTrack audioTrack;


    /**
     * AIUI 回调信息处理
     */
    private AIUIListener aiuiListener = event -> {
        switch (event.eventType) {
            case AIUIConstant.EVENT_RESULT:
                if (event.info.contains("\"sub\":\"tts")) {
                    //开发者自己用播放器来合成,需要在aiui.cfg中将"play_mode":"sdk"配置成"play_mode":"user"
//                    byte[] audio = event.data.getByteArray("0"); //tts音频数据，16k，16bit格式
//                    byte[] processedTTS = TtsFilterUtil.filter(audio, 500);//过滤tts无效音频
//                    audioTrack.write(processedTTS, 0, processedTTS.length);
//                    audioTrack.play();
                }
                break;

            case AIUIConstant.EVENT_ERROR:
                setText("错误码: " + event.arg1);
                setText("错误信息:" + event.info);
                setText("解决方案:" + ErrorCode.getError(event.arg1) + "\n  错误解决详情参考：https://www.yuque.com/iflyaiui/zzoolv/igbuol");
                break;

            case AIUIConstant.EVENT_STATE:    // 状态事件
                EngineConstants.mAIUIState = event.arg1;
                break;

            default:
                break;
        }
    };


    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_asr);
        initLayout();
        // 资源拷贝
        CopyAssetsUtils.portingFile(this);
        int bufferSizeInBytes = AudioRecord.getMinBufferSize(
                16000, AudioFormat.CHANNEL_IN_MONO, AudioFormat.ENCODING_PCM_16BIT);

        audioTrack = new AudioTrack(AudioManager.STREAM_SYSTEM, 16000, AudioFormat.CHANNEL_OUT_MONO, AudioFormat.ENCODING_PCM_16BIT,
                bufferSizeInBytes, AudioTrack.MODE_STREAM);
    }

    private void initLayout() {
        findViewById(R.id.init_sdk).setOnClickListener(this);
        findViewById(R.id.btnStartRecord).setOnClickListener(this);
        findViewById(R.id.btnStopRecord).setOnClickListener(this);
        findViewById(R.id.btnSave).setOnClickListener(this);
        TextView titleTextView = findViewById(R.id.myTitle);
        titleTextView.setText("离线语音合成");
        mScrollView = findViewById(R.id.scrollView);
        mResText = findViewById(R.id.res_text);
        mResText.append("可以通过接口修改发音人，音量，语速。部分发音人需要付费开通 \n");
    }

    @Override
    public void onClick(View view) {
        int id = view.getId();
        if (id == R.id.init_sdk) {
            initSDK();
        } else if (id == R.id.btnStartRecord) {
            startTTS();
        }
    }

    private void initSDK() {
        //TODO 开发者需要实现生成sn的代码，参考：https://www.yuque.com/iflyaiui/zzoolv/tgftb5
        //注意事项1: sn每台设备需要唯一！！！！WakeupEngine的sn和AIUI的sn要一致
        //注意事项2: 获取的值要保持稳定，否则会重复授权，浪费授权量
        EngineConstants.serialNumber = "iflytek-test";
        Log.i(TAG, "sn: " + EngineConstants.serialNumber);
        // 初始化AIUI(识别+语义+合成）
        mAIUIAgent = AiuiEngine.getInstance(aiuiListener, "cfg/aiui_localtts.cfg");
        if (mAIUIAgent != null) {
            setText("AIUI初始化成功");
        } else {
            setText("AIUI初始化失败");
        }
        //设置tts为sdk自动播放(演示方便，实际产品手动控制播放比较方便)
        AiuiEngine.TTS_playBySdk();
    }


    private void startTTS() {
        String text = "tts测试，可以通过接口修改发音人，音量，语速";
        StringBuffer params = new StringBuffer();

//****动态切换在线tts。离在线场景最好最用纯离线tts，简化代码逻辑***************
//        AiuiEngine.MSG_setSimpleParam("tts","engine_type","online");
//        params.append("vcn=x2_xiaojuan");
//****动态切换在线tts。离在线场景最好最用纯离线tts，简化代码逻辑***************

        //离线发音人需要aiui.cfg配置发音人资源，绑定了appid，正式签约后讯飞提供资源文件
        params.append("vcn=xiaoyan");
        //语速，取值范围[0,100]
        params.append(",speed=55");
        //音调，取值范围[0,100]
        params.append(",pitch=50");
        //音量，取值范围[0,100]
        params.append(",volume=55");
        AiuiEngine.TTS_start(text, params);
    }

    /**
     * 根据scrollView 和子view去测量滑动的位置
     *
     * @param scrollView
     * @param view
     */
    private void scrollToBottom(final ScrollView scrollView, final View view) {

        handler.post(() -> {
            if (scrollView == null || view == null) {
                return;
            }
            // offset偏移量。是指当textview中内容超出 scrollview的高度，那么超出部分就是偏移量
            int offset = view.getMeasuredHeight()
                    - scrollView.getMeasuredHeight();
            if (offset < 0) {
                offset = 0;
            }
            //scrollview开始滚动
            scrollView.scrollTo(0, offset);
        });
    }

    //打印到屏幕
    private void setText(final String str) {
        if (Looper.getMainLooper() == Looper.myLooper()) {
            mResText.append(str + " \n");
            scrollToBottom(mScrollView, mResText);
        } else {
            runOnUiThread(() -> {
                mResText.append(str + " \n");
                scrollToBottom(mScrollView, mResText);
            });
        }
    }

    @Override
    protected void onDestroy() {
        super.onDestroy();
        if (aiuiListener != null) {
            aiuiListener = null;
        }
        AiuiEngine.destroy();
    }
}